home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Atari Compendium
/
The Atari Compendium (Toad Computers) (1994).iso
/
files
/
umich
/
network
/
ka9q
/
ka9q_src.arc
/
ICMP.C
< prev
next >
Wrap
C/C++ Source or Header
|
1988-07-28
|
5KB
|
189 lines
/* Internet Control Message Protocol */
#include "global.h"
#include "mbuf.h"
#include "internet.h"
#include "timer.h"
#include "iface.h"
#include "ip.h"
#include "icmp.h"
struct icmp_errors icmp_errors;
struct icmp_stats icmp_stats;
/* Process an incoming ICMP packet */
void
icmp_input(bp,protocol,source,dest,tos,length,rxbroadcast)
struct mbuf *bp; /* Pointer to ICMP message */
char protocol; /* Should always be ICMP_PTCL */
int32 source; /* Sender of ICMP message */
int32 dest; /* Us */
char tos; /* Type of Service */
int16 length; /* Length of ICMP message */
char rxbroadcast;
{
struct mbuf *htonicmp();
struct icmp icmp; /* ICMP header */
struct ip ip; /* Offending datagram header */
int16 type; /* Type of ICMP message */
extern int pingflag; /* DG2KK */
if(rxbroadcast){
/* Broadcast ICMP packets are to be IGNORED !! */
icmp_errors.bdcsts++;
free_p(bp);
return;
}
if(cksum(NULLHEADER,bp,length) != 0){
/* Bad ICMP checksum; discard */
icmp_errors.checksum++;
free_p(bp);
return;
}
ntohicmp(&icmp,&bp);
/* Process the message. Some messages are passed up to the protocol
* module for handling, others are handled here.
*/
type = icmp.type & 0xff;
if(type < ICMP_TYPES)
icmp_stats.input[type]++;
switch(type){
case TIME_EXCEED: /* Time-to-live Exceeded */
case DEST_UNREACH: /* Destination Unreachable */
case QUENCH: /* Source Quench */
ntohip(&ip,&bp); /* Extract offending IP header */
switch(ip.protocol){
case TCP_PTCL:
tcp_icmp(ip.source,ip.dest,icmp.type,icmp.code,&bp);
break;
}
break;
case ECHO: /* Echo Request */
/* Change type to ECHO_REPLY, recompute checksum,
* and return datagram.
*/
/* DG2KK: don't send an ECHO_REPLY if pingflag is 'off' */
if(pingflag == 0)
return;
icmp.type = ECHO_REPLY;
bp = htonicmp(&icmp,bp);
icmp_stats.output[ECHO_REPLY]++;
ip_send(dest,source,ICMP_PTCL,tos,0,bp,length,0,0);
return;
case REDIRECT: /* Redirect */
case PARAM_PROB: /* Parameter Problem */
break;
case ECHO_REPLY: /* Echo Reply */
echo_proc(source,dest,&icmp);
break;
case TIMESTAMP: /* Timestamp */
case TIME_REPLY: /* Timestamp Reply */
case INFO_RQST: /* Information Request */
case INFO_REPLY: /* Information Reply */
break;
}
free_p(bp);
}
/* Return an ICMP response to the sender of a datagram */
icmp_output(ip,bp,type,code,args)
struct ip *ip; /* Header of offending datagram */
struct mbuf *bp; /* Data portion of datagram */
char type,code; /* Codes to send */
union icmp_args *args;
{
struct mbuf *htonicmp();
struct mbuf *htonip();
struct icmp icmp; /* ICMP protocol header */
int16 dlen; /* Length of data portion of offending pkt */
int16 length; /* Total length of reply */
extern int32 ip_addr; /* Our IP address */
if(ip == NULLIP)
return;
if(type < ICMP_TYPES)
icmp_stats.output[type]++;
if(ip->protocol == ICMP_PTCL){
/* Never send an ICMP message about another ICMP message */
icmp_errors.noloop++;
return;
}
/* Compute amount of original datagram to return.
* We return the original IP header, and up to 8 bytes past that.
*/
dlen = min(8,len_mbuf(bp));
length = dlen + ICMPLEN + IPLEN + ip->optlen;
if(bp != NULLBUF){
/* Take excerpt from data portion */
bp = copy_p(bp,dlen);
}
/* Recreate and tack on offending IP header */
bp = htonip(ip,bp);
icmp.type = type;
icmp.code = code;
switch(icmp.type){
case PARAM_PROB:
icmp.args.pointer = args->pointer;
break;
case REDIRECT:
icmp.args.address = args->address;
break;
case ECHO:
case ECHO_REPLY:
case INFO_RQST:
case INFO_REPLY:
case TIMESTAMP:
case TIME_REPLY:
icmp.args.echo.id = args->echo.id;
icmp.args.echo.seq = args->echo.seq;
break;
default:
icmp.args.unused = 0;
break;
}
bp = htonicmp(&icmp,bp); /* Now stick on the ICMP header */
ip_send(ip_addr,ip->source,ICMP_PTCL,ip->tos,0,bp,length,0,0);
}
/* Generate ICMP header in network byte order, link data, compute checksum */
struct mbuf *
htonicmp(icmp,data)
struct icmp *icmp;
struct mbuf *data;
{
struct mbuf *rval;
register char *cp;
int16 checksum;
rval = alloc_mbuf(ICMPLEN);
rval->cnt = ICMPLEN;
cp = rval->data;
*cp++ = icmp->type;
*cp++ = icmp->code;
cp = put16(cp,0); /* Clear checksum */
cp = put16(cp,icmp->args.echo.id);
cp = put16(cp,icmp->args.echo.seq);
/* Link in data, compute checksum, and stash result */
rval->next = data;
checksum = cksum(NULLHEADER,rval,len_mbuf(rval));
cp = &rval->data[2];
cp = put16(cp,checksum);
return rval;
}
/* Pull off ICMP header */
ntohicmp(icmp,bpp)
struct icmp *icmp;
struct mbuf **bpp;
{
icmp->type = pullchar(bpp);
icmp->code = pullchar(bpp);
(void) pull16(bpp); /* Toss checksum */
icmp->args.echo.id = pull16(bpp);
icmp->args.echo.seq = pull16(bpp);
}